Palindrome partitioning III¶
Time: O(KxN^2); Space: O(N^2); hard
You are given a string s containing lowercase letters and an integer k. You need to : * First, change some characters of s to other lowercase English letters. * Then divide s into k non-empty disjoint substrings such that each substring is palindrome.
Return the minimal number of characters that you need to change to divide the string.
Example 1:
Input: s = “abc”, k = 2
Output: 1
Explanation: You can split the string into “ab” and “c”, and change 1 character in “ab” to make it palindrome.
Example 2:
Input: s = “aabbc”, k = 3
Output: 0
Explanation: You can split the string into “aa”, “bb” and “c”, all of them are palindrome.
Example 3:
Input: s = “leetcode”, k = 8
Output: 0
Constraints:
1 <= k <= len(s) <= 100.
s only contains lowercase English letters.
Hints:
For each substring calculate the minimum number of steps to make it palindrome and store it in a table.
Create a dp(pos, cnt) which means the minimum number of characters changed for the suffix of s starting on pos splitting the suffix on cnt chunks.
1. Dynamic programming [O(K*N^2), O(N^2)]¶
[4]:
class Solution1(object):
"""
Time: O(K*N^2)
Space: O(N^2)
"""
def palindromePartition(self, s, k):
"""
:type s: str
:type k: int
:rtype: int
"""
# dp1[i][j]: minimum number of changes to make s[i, j] palindrome
dp1 = [[0]*len(s) for _ in range(len(s))]
for l in range(1, len(s)+1):
for i in range(len(s)-l+1):
j = i+l-1
if i == j-1:
dp1[i][j] = 0 if s[i] == s[j] else 1
elif i != j:
dp1[i][j] = dp1[i+1][j-1] if s[i] == s[j] else dp1[i+1][j-1]+1
# dp2[d][i]: minimum number of changes to divide s[0, i] into d palindromes
dp2 = [[float("inf")]*len(s) for _ in range(2)]
dp2[1] = dp1[0][:]
for d in range(2, k+1):
dp2[d%2] = [float("inf")]*len(s)
for i in range(d-1, len(s)):
for j in range(d-2, i):
dp2[d%2][i] = min(dp2[d%2][i], dp2[(d-1)%2][j]+dp1[j+1][i])
return dp2[k%2][len(s)-1]
[5]:
sol = Solution1()
s = "abc"
k = 2
assert sol.palindromePartition(s, k) == 1
s = "aabbc"
k = 3
assert sol.palindromePartition(s, k) == 0
s = "leetcode"
k = 8
assert sol.palindromePartition(s, k) == 0